/*************************************************************
 * Title: 
 * Description: 
 * Author: Snow Huang
 * Email: Shaobin.Software@gmail.com Shaobin_Software@163.com
 * CreateTime: Aug 20, 2010 2:29:23 PM
 * Copyright © 落羽社区 All right reserved
 ************************************************************/
package snow.core.domain.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;

import snow.core.domain.query.Query;
import snow.core.util.toolkit.CollectionHelper;
import snow.core.util.toolkit.HibernateHelper;

/**
 * 
 */
public abstract class HibernateDao<Entity, Identity extends Serializable> extends BaseDao<Entity, Identity> {

	private HibernateTemplate hibernateTemplate;

	private Class<Entity> entityClass; // 实体类的Class对象
	private Class<Identity> identityClass; // 实体主键类的Class对象

	/**
	 * HibernateDao构造器，要求子类传入相应的Class对象
	 */
	protected HibernateDao(Class<Entity> entityClass, Class<Identity> identityClass) {
		Assert.notNull(entityClass, "The entity class must not be null!");
		Assert.notNull(identityClass, "The identity class must not be null!");
		this.entityClass = entityClass;
		this.identityClass = identityClass;
	}
	
	protected final DetachedCriteria getDetachedCriteria() {
		return DetachedCriteria.forClass(entityClass);
	}
	
	protected final List<Entity> find(Query<Entity> query) {
		DetachedCriteria criteria = getDetachedCriteria();
		HibernateHelper.addCriteria(criteria, query); // 添加查询条件
		HibernateHelper.addOrder(criteria, query.getOrders()); // 排序
		return CollectionHelper.getNewListFrom(getHibernateTemplate().findByCriteria(criteria, query.getStartIndex(), query.getLimitSize()), entityClass);
	}
	
	protected final List<Entity> find(String hql) {
		return find(hql, (Object) null);
	}

	protected final List<Entity> find(String hql, Object value) {
		return find(hql, new Object[] { value });
	}

	protected final List<Entity> find(String hql, Object... values) {
		return CollectionHelper.getNewListFrom(getHibernateTemplate().find(hql, values), entityClass);
	}

	protected void checkDaoConfig() {
		super.checkDaoConfig(); // 调用父类的checkDaoConfig
		if (getHibernateTemplate() == null) { // 检验Hibernate模板是否为空
			throw new IllegalArgumentException("'hibernateTemplate' is required");
		}
	}

	/**
	 * @param entity
	 * @see snow.core.commons.dao.BaseDao#delete(java.lang.Object)
	 */
	protected void delete(Entity entity) {
		getHibernateTemplate().delete(entity);
	}

	/**
	 * @param identity
	 * @return
	 * @see snow.core.commons.dao.BaseDao#get(java.lang.Object)
	 */
	protected Entity get(Identity identity) {
		return getHibernateTemplate().get(entityClass, identity);
	}

	/**
	 * @return the hibernateTemplate
	 */
	public final HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	/**
	 * @param identity
	 * @return
	 * @see snow.core.commons.dao.BaseDao#load(java.lang.Object)
	 */
	protected Entity load(Identity identity) {
		return getHibernateTemplate().load(entityClass, identity);
	}

	/**
	 * @return
	 * @see snow.core.commons.dao.BaseDao#loadAll()
	 */
	protected List<Entity> loadAll() {
		return getHibernateTemplate().loadAll(entityClass);
	}

	/**
	 * @param entity
	 * @return
	 * @see snow.core.commons.dao.BaseDao#save(java.lang.Object)
	 */
	protected Identity save(Entity entity) {
		return identityClass.cast(getHibernateTemplate().save(entity));
	}

	/**
	 * @param entity
	 * @see snow.core.commons.dao.BaseDao#saveOrUpdate(java.lang.Object)
	 */
	protected void saveOrUpdate(Entity entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}

	/**
	 * @param hibernateTemplate
	 *            the hibernateTemplate to set
	 */
	public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	/**
	 * @param entity
	 * @see snow.core.commons.dao.BaseDao#update(java.lang.Object)
	 */
	protected void update(Entity entity) {
		getHibernateTemplate().update(entity);
	}
}
